//
// GPSMapEdit
// (c) Konstantin Galichsky (kg@geopainting.com), 2006
//
// Import wizard - city attribute interpreter.
//

# include "StdAfx.h"
# include "ShpExtraLoader.h"
# include "Transliteration.h"
# include "Transform.h"
# include "ShpWizard.h"
# include "DatabaseTable.h"
# include "ParseHelpers.h"

void CShpExtraLoader::Bind (CShpWizard * _pWizard, const CDatabaseTable * _pDbt, map_t * _pMap) {
	m_pDbt    = _pDbt;
	m_pMap    = _pMap;
	m_pWizard = _pWizard;
}

int CShpExtraLoader::_GetInt (size_t _cRecordCounter, input_attr_t _ia) const {
	const size_t cFieldIndex = m_pWizard->m_cFields [_ia];
	if (cFieldIndex == -1)
		return 0;

	const size_t cFieldLen = m_pDbt->GetFieldMaxLength (_cRecordCounter, cFieldIndex);
	char * const strBuf = reinterpret_cast<char *> (::alloca ((cFieldLen + 1)*sizeof (char)));
	const size_t cLen = m_pDbt->GetFieldS (_cRecordCounter, cFieldIndex, strBuf);
	if (cLen == 0)
		return 0;

	unsigned long ul = 0;
	const char * pEnd = NULL;
	if (! ParseDecU (strBuf, strBuf + cLen, & pEnd, ul))
		return 0;

	return ul;
}

bool CShpExtraLoader::_GetBool (size_t _cRecordCounter, input_attr_t _ia) const {
	return _GetInt (_cRecordCounter, _ia) != 0;
}

void CShpExtraLoader::_GetString (size_t _cRecordCounter, input_attr_t _ia, string_t & _str) const {
	const size_t cFieldIndex = m_pWizard->m_cFields [_ia];
	if (cFieldIndex == -1)
		return;

	const size_t cFieldLen = m_pDbt->GetFieldMaxLength (_cRecordCounter, cFieldIndex);
	char * const strBuf = reinterpret_cast<char *> (::alloca ((cFieldLen + 1)*sizeof (char)));
	const size_t cLen = m_pDbt->GetFieldS (_cRecordCounter, cFieldIndex, strBuf);
	if (cLen == 0)
		return;

	if (m_pWizard->GetOEM ())
		::OemToCharBuff (strBuf, strBuf, cLen);

	if (m_pWizard->GetTransliterator ()) {
		m_pWizard->GetTransliterator ()->Do (strBuf, strBuf + cLen, _str);
	} else
		_str.assign (strBuf, cLen);
}

city_t * CShpExtraLoader::GetCity (size_t _cRecordCounter) {
	string_t strCity;
	_GetString (_cRecordCounter, iaCity, strCity);
	if (strCity.empty ())
		return NULL;

	string_t strFullName = strCity;

	string_t strRegion;
	string_t strCountry;
	_GetString (_cRecordCounter, iaRegion, strRegion);
	if (! strRegion.empty ()) {
		strFullName.append (1, '|');
		strFullName.append (strRegion);

		_GetString (_cRecordCounter, iaCountry, strCountry);
		if (! strCountry.empty ()) {
			strFullName.append (1, '|');
			strFullName.append (strCountry);
		}
	}

	const name2city_t::const_iterator i = m_name2city.find (strFullName);
	if (i != m_name2city.end ())
		return i->second;

	// Find country.
	country_t * pCountry = NULL;
	for (countries_t::iterator ci = m_pMap->Countries.begin (); ci != m_pMap->Countries.end (); ++ ci) {
		country_t & country = * ci;
		if (country.IsDeleted ())
			continue;

		if (country.strName == strCountry) {
			pCountry = & country;
			break;
		}
	}
	if (pCountry == NULL) {
		m_pMap->Countries.push_back (country_t ());
		pCountry = & m_pMap->Countries.back ();
		pCountry->strName.swap (strCountry);
	}

	// Find region.
	region_t * pRegion = NULL;
	for (regions_t::iterator ri = m_pMap->Regions.begin (); ri != m_pMap->Regions.end (); ++ ri) {
		region_t & region = * ri;
		if (region.IsDeleted ())
			continue;

		if (region.strName == strRegion && region.pCountry == pCountry) {
			pRegion = & region;
			break;
		}
	}
	if (pRegion == NULL) {
		m_pMap->Regions.push_back (region_t ());
		pRegion = & m_pMap->Regions.back ();
		pRegion->pCountry = pCountry;
		pRegion->strName.swap (strRegion);
	}

	// Create city.
	m_pMap->Cities.push_back (city_t ());
	city_t & city = m_pMap->Cities.back ();
	city.strName.swap (strCity);
	city.pRegion = pRegion;

	m_name2city.insert (name2city_t::value_type (city.strName, & city));

	return & city;
}

zip_t * CShpExtraLoader::GetZip (size_t _cRecordCounter) {
	string_t strZip;
	_GetString (_cRecordCounter, iaZipCode, strZip);
	if (strZip.empty ())
		return NULL;

	const name2zip_t::const_iterator i = m_name2zip.find (strZip);
	if (i != m_name2zip.end ())
		return i->second;

	// Create zip code.
	m_pMap->Zips.push_back (zip_t ());
	zip_t & zip = m_pMap->Zips.back ();
	zip.strName.swap (strZip);

	m_name2zip.insert (name2zip_t::value_type (zip.strName, & zip));

	return & zip;
}

void CShpExtraLoader::ReadExtra (size_t _cRecordCounter, extra_t & _extra) {
	_GetString (_cRecordCounter, iaComment, _extra.strComment);
	_extra.cEndLevel = _GetInt (_cRecordCounter, iaEndLevel);
	
	_GetString (_cRecordCounter, iaNumber, _extra.strNumber);
	_GetString (_cRecordCounter, iaStreet, _extra.strStreet);
	_extra.pCity = GetCity (_cRecordCounter);
	_extra.pZip  = GetZip  (_cRecordCounter);

	_GetString (_cRecordCounter, iaPhone,       _extra.strPhone);
	_GetString (_cRecordCounter, iaFax,         _extra.strFax);
	_GetString (_cRecordCounter, iaEmail,       _extra.strEmail);
	_GetString (_cRecordCounter, iaWebPage,     _extra.strWebPage);
	_GetString (_cRecordCounter, iaDescription, _extra.strDescription);

	_extra.bDirIndicator = _GetBool (_cRecordCounter, iaDirIndicator);

	_extra.fSpeedLimit   = _GetInt  (_cRecordCounter, iaSpeedLimit);
	_extra.fRouteClass   = _GetInt  (_cRecordCounter, iaRouteClass);
	_extra.bOneWay       = _GetBool (_cRecordCounter, iaOneWay);
	_extra.bToll         = _GetBool (_cRecordCounter, iaToll);
	_extra.bNoEmergency  = _GetBool (_cRecordCounter, iaNoEmergency);
	_extra.bNoDelivery   = _GetBool (_cRecordCounter, iaNoDelivery);
	_extra.bNoCar        = _GetBool (_cRecordCounter, iaNoCar);
	_extra.bNoBus        = _GetBool (_cRecordCounter, iaNoBus);
	_extra.bNoTaxi       = _GetBool (_cRecordCounter, iaNoTaxi);
	_extra.bNoPedestrian = _GetBool (_cRecordCounter, iaNoPedestrian);
	_extra.bNoBicycle    = _GetBool (_cRecordCounter, iaNoBicycle);
	_extra.bNoTruck      = _GetBool (_cRecordCounter, iaNoTruck);
}

void CShpExtraLoader::SetRgnExtraAttributes (rgn_t & _rgn, extra_t & _extra) {
	_rgn.strComment.swap (_extra.strComment);
	_rgn.uchEndLevel = _extra.cEndLevel;

	if (! _extra.strNumber.empty ())
		_rgn.pExtra->strNumber.swap (_extra.strNumber);
	if (! _extra.strStreet.empty ())
		_rgn.pExtra->strStreetDesc.swap (_extra.strStreet);
	if (_extra.pCity)
		_rgn.pExtra->pCity = _extra.pCity;
	if (_extra.pZip)
		_rgn.pExtra->pZip  = _extra.pZip;

	if (! _extra.strPhone.empty ())
		_rgn.pExtra->strPhone.swap (_extra.strPhone);
	if (! _extra.strFax.empty ())
		_rgn.pExtra->strFax.swap (_extra.strFax);
	if (! _extra.strEmail.empty ())
		_rgn.pExtra->strEmail.swap (_extra.strEmail);
	if (! _extra.strWebPage.empty ())
		_rgn.pExtra->strWebPage.swap (_extra.strWebPage);
	if (! _extra.strDescription.empty ())
		_rgn.pExtra->strDescription.swap (_extra.strDescription);

	if (_rgn.IsPolyline ()) {
		if (_extra.bDirIndicator)
			_rgn.dwFlags |= rgn_t::fDirIndicator;

		if (
			_extra.fSpeedLimit != 0 ||
			_extra.fRouteClass != 0 ||
			_extra.bOneWay	        ||
			_extra.bToll		    ||
			_extra.bNoEmergency		||
			_extra.bNoDelivery		||
			_extra.bNoCar       	||
			_extra.bNoBus       	||
			_extra.bNoTaxi      	||
			_extra.bNoPedestrian	||
			_extra.bNoBicycle   	||
			_extra.bNoTruck
		) {
			_rgn.pExtra->fSpeedLimit   = _extra.fSpeedLimit;
			_rgn.pExtra->fRouteClass   = _extra.fRouteClass;

			_rgn.pExtra->bOneWay       = _extra.bOneWay;
			_rgn.pExtra->bToll         = _extra.bToll;

			_rgn.pExtra->bNoEmergency  = _extra.bNoEmergency;
			_rgn.pExtra->bNoDelivery   = _extra.bNoDelivery;
			_rgn.pExtra->bNoCar        = _extra.bNoCar;
			_rgn.pExtra->bNoBus        = _extra.bNoBus;
			_rgn.pExtra->bNoTaxi       = _extra.bNoTaxi;
			_rgn.pExtra->bNoPedestrian = _extra.bNoPedestrian;
			_rgn.pExtra->bNoBicycle    = _extra.bNoBicycle;
			_rgn.pExtra->bNoTruck      = _extra.bNoTruck;
		}
	}
}